package com.star.spring.ratelimit.limiter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * Redis固定窗口限流器
 * 
 * @author star
 * @since 2025-01-24
 */
@Slf4j
@Component
public class RedisFixedWindowLimiter {

    private final RedisTemplate<String, Object> redisTemplate;

    public RedisFixedWindowLimiter(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 尝试获取请求许可
     * 
     * @param key 限流key
     * @param maxRequests 最大请求数
     * @param windowSizeSeconds 窗口大小（秒）
     * @return 是否获取成功
     */
    public boolean tryAcquire(String key, int maxRequests, int windowSizeSeconds) {
        try {
            // 计算当前窗口的key
            long currentWindow = System.currentTimeMillis() / (windowSizeSeconds * 1000L);
            String windowKey = key + ":" + currentWindow;
            
            // 获取当前窗口的请求数
            Object countObj = redisTemplate.opsForValue().get(windowKey);
            int currentCount = countObj != null ? Integer.parseInt(countObj.toString()) : 0;
            
            if (currentCount >= maxRequests) {
                log.debug("Redis fixed window limiter - key: {}, currentCount: {}, maxRequests: {}, acquired: false", 
                        key, currentCount, maxRequests);
                return false;
            }
            
            // 增加计数
            redisTemplate.opsForValue().increment(windowKey);
            // 设置过期时间
            redisTemplate.expire(windowKey, windowSizeSeconds, TimeUnit.SECONDS);
            
            log.debug("Redis fixed window limiter - key: {}, currentCount: {}, maxRequests: {}, acquired: true", 
                    key, currentCount + 1, maxRequests);
            return true;
            
        } catch (Exception e) {
            log.error("Redis fixed window limiter error - key: {}", key, e);
            // Redis异常时允许通过
            return true;
        }
    }

    /**
     * 尝试获取请求许可（使用默认参数）
     * 
     * @param key 限流key
     * @return 是否获取成功
     */
    public boolean tryAcquire(String key) {
        return tryAcquire(key, 1000, 60);
    }

    /**
     * 获取当前窗口的请求数
     * 
     * @param key 限流key
     * @param windowSizeSeconds 窗口大小（秒）
     * @return 当前请求数
     */
    public int getCurrentCount(String key, int windowSizeSeconds) {
        try {
            long currentWindow = System.currentTimeMillis() / (windowSizeSeconds * 1000L);
            String windowKey = key + ":" + currentWindow;
            
            Object countObj = redisTemplate.opsForValue().get(windowKey);
            return countObj != null ? Integer.parseInt(countObj.toString()) : 0;
        } catch (Exception e) {
            log.error("Get current count error - key: {}", key, e);
            return 0;
        }
    }
}
